/*
 * Copyright 2009 Cedric Priscal
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.serialport.sample;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.serialport.SerialPort;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;

public abstract class SerialPortActivity extends Activity {

    protected Application mApplication;
    protected SerialPort mSerialPort;
    protected OutputStream mOutputStream;
    private InputStream mInputStream;
    private ReadThread mReadThread;
    private String TAG = "SerialPortActivity";

    // 负责从串口读取数据并调用 onDataReceived 方法处理接收到的数据
    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            Log.e(TAG, "ReadThread started");
            while (!isInterrupted()) {
                int size;
                try {
                    byte[] buffer = new byte[64];
                    if (mInputStream == null) {
                        Log.e(TAG, "mInputStream is null");
                        return;
                    }
                    // InputStream.read是阻塞的，只有当有数据可读时才会返回，这种方式已经比较节省资源。
                    size = mInputStream.read(buffer);
                    if (size > 0) {
                        Log.e(TAG, "Data received, size: " + size);
                        onDataReceived(buffer, size);
                    } else {
                        Log.e(TAG, "No data received");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
            Log.e(TAG, "ReadThread interrupted");
        }
    }

    // 显示错误对话框，并在用户确认后结束当前活动
    private void DisplayError(int resourceId) {
        AlertDialog.Builder b = new AlertDialog.Builder(this);
        b.setTitle("Error");
        b.setMessage(resourceId);
        b.setPositiveButton("OK", new OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                SerialPortActivity.this.finish();
            }
        });
        b.show();
    }

    // 初始化串口和数据接收线程
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mApplication = (Application) getApplication();
        try {
            mSerialPort = mApplication.getSerialPort();
            mOutputStream = mSerialPort.getOutputStream();
            mInputStream = mSerialPort.getInputStream();

            if (mOutputStream != null) {
                Log.e(TAG, "mOutputStream initialized successfully");
            } else {
                Log.e(TAG, "mOutputStream is null");
            }

            if (mInputStream != null) {
                Log.e(TAG, "mInputStream initialized successfully");
            } else {
                Log.e(TAG, "mInputStream is null");
            }

            /* Create a receiving thread */
            mReadThread = new ReadThread();
            mReadThread.start();
            Log.e(TAG, "mReadThread is running");
        } catch (SecurityException e) {
            DisplayError(R.string.error_security);
        } catch (IOException e) {
            DisplayError(R.string.error_unknown);
        } catch (InvalidParameterException e) {
            DisplayError(R.string.error_configuration);
        }
    }

    // 抽象方法，子类需要实现，用于处理接收到的数据
    protected abstract void onDataReceived(final byte[] buffer, final int size);

    @Override
    protected void onDestroy() {
        if (mReadThread != null) mReadThread.interrupt();
        if (mOutputStream != null) {
            try {
                mOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mInputStream != null) {
            try {
                mInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        mApplication.closeSerialPort();
        mSerialPort = null;
        super.onDestroy();
    }
}
